Skip to content

feat: Ideogram structured-caption nodes (CORE-292)#14537

Open
jtydhr88 wants to merge 2 commits into
masterfrom
feat/ideogram-prompt-nodes
Open

feat: Ideogram structured-caption nodes (CORE-292)#14537
jtydhr88 wants to merge 2 commits into
masterfrom
feat/ideogram-prompt-nodes

Conversation

@jtydhr88

@jtydhr88 jtydhr88 commented Jun 18, 2026

Copy link
Copy Markdown
Contributor

Two dedicated nodes for building Ideogram 4's structured JSON caption:

  • Create Bounding Boxes: visual region editor -> caption elements (COMFY_LIST), pixel-space bounding boxes (BOUNDING_BOX), and a rendered preview (IMAGE).
  • Build JSON Prompt (Ideogram): assembles the elements plus background and style fields into the caption (COMFY_DICT).

Adds the COMFY_DICT, COMFY_LIST, COLORS, and BOUNDING_BOXES io types;
Made COLORS and BOUNDING_BOXES so the editor widgets pass native values.
Create Bounding Boxes lives in nodes_bounding_boxes.py,
Build JSON Prompt (Ideogram) in nodes_json_prompt.py, shared color helpers in color_util.py.

Also adds a Dict to JSON String node (nodes_string.py) that serializes a COMFY_DICT with ensure_ascii=False, so non-ASCII captions render as real characters instead of \uXXXX escapes.

Screenshot
image

workflow
image_ideogram4_t2i (2).json

some design refer to KJ's node

need FE: Comfy-Org/ComfyUI_frontend#12960

@coderabbitai

coderabbitai Bot commented Jun 18, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

Walkthrough

This PR introduces four new ComfyType IO classes (Dict, Array, Colors, BoundingBoxes) in comfy_api/latest/_io.py. A new comfy_extras/color_util.py module provides hex_to_rgb, readable_color, and normalize_palette helpers. comfy_extras/nodes_bounding_boxes.py adds the CreateBoundingBoxes node, which parses user-drawn regions from editor_state into a preview image, a pixel-space bounding-box frame, and caption elements. comfy_extras/nodes_json_prompt.py adds BuildJsonPromptIdeogram, which assembles a structured JSON caption dict for Ideogram 4 workflows. comfy_extras/nodes_string.py gains ConvertDictionaryToString and ConvertArrayToString nodes. Both new node modules are registered in nodes.py for startup loading. The existing ColorToRGBInt node is refactored to use the new hex_to_rgb utility.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 2.78% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly and specifically summarizes the main addition: two new Ideogram nodes for building structured captions, with CORE-292 issue reference.
Description check ✅ Passed The description is directly related to the changeset, detailing the two new nodes, new I/O types, file organization, and additional features like the Dict to JSON String node.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_extras/color_util.py`:
- Around line 1-5: The hex_to_rgb function lacks error handling for invalid
hexadecimal characters within the 6-character string, which causes ValueError
exceptions when int() attempts to parse non-hex values like "ZZZZZZ". Wrap the
three int() conversion calls at the return statement in a try-except block that
catches ValueError, and return the same default white color tuple (255, 255,
255) when a conversion fails, ensuring graceful handling of malformed hex input
without crashing the preview render.

In `@comfy_extras/nodes_json_prompt.py`:
- Around line 52-58: The style_desc dictionary in the function is
unconditionally including aesthetics, lighting, and medium values even when they
are empty strings, which violates the documented contract that blank values
should be omitted. Modify the dictionary construction to only add these keys
(aesthetics, lighting, medium in the initial block and photo, art_style in the
conditional blocks) if their corresponding values are non-empty strings. Check
each value before adding it to style_desc to ensure only non-blank values are
included.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: d2ab3530-b604-4d79-8af3-f3756db91001

📥 Commits

Reviewing files that changed from the base of the PR and between 16514da and f9d88f5.

📒 Files selected for processing (6)
  • comfy_api/latest/_io.py
  • comfy_extras/color_util.py
  • comfy_extras/nodes_bounding_boxes.py
  • comfy_extras/nodes_json_prompt.py
  • comfy_extras/nodes_string.py
  • nodes.py

Comment thread comfy_extras/color_util.py Outdated
Comment thread comfy_extras/nodes_json_prompt.py
@jtydhr88 jtydhr88 force-pushed the feat/ideogram-prompt-nodes branch 2 times, most recently from 12ff69d to c6d1759 Compare June 18, 2026 18:24
@alexisrolland alexisrolland changed the title feat: Ideogram structured-caption nodes feat: Ideogram structured-caption nodes (CORE-292) Jun 19, 2026
@jtydhr88 jtydhr88 force-pushed the feat/ideogram-prompt-nodes branch from c6d1759 to 850c913 Compare June 20, 2026 02:17
Comment thread comfy_extras/nodes_string.py Outdated
Comment thread comfy_extras/nodes_string.py Outdated
Comment thread comfy_api/latest/_io.py
self.default = []


@comfytype(io_type="BOUNDING_BOXES")

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Would it make sense and would it be possible to reuse the existing type @comfytype(io_type="BBOX")?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same situation as COLORS, plus a shape mismatch.

the BOUNDING_BOXES is a concrete list[{x, y, width, height, metadata: {type, text, desc, palette}}], and it has to map to our canvas editor widget.

Two reasons we can't reuse BBOX:

  • No wrap-into-array mechanism (same as COLOR): there's no backend flag or frontend path to take a single type and render/declare it as an array-valued editor widget. A dedicated @comfytype with Type = list[...] and its own Input is the only way to get the editor widget, that's BOUNDING_BOXES.
  • Shape: we need a concrete per-box contract incl. metadata (type/text/desc/palette); BBOX = Any carries no shape. Note we do reuse the existing structured single type, BOUNDING_BOXES.BoundingBoxWithMetadata extends BoundingBox.BoundingBoxDict ({x, y, width, height}) and just adds metadata.

So BOUNDING_BOXES reuses the existing BOUNDING_BOX shape where it fits and exists as a distinct list type purely to drive the editor widget.

Comment thread comfy_api/latest/_io.py Outdated
Comment thread comfy_api/latest/_io.py Outdated
io.String.Input("background", multiline=True, default="",
tooltip="Scene background description."),
io.DynamicCombo.Input("style", options=[
io.DynamicCombo.Option("none", []),

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should remove this option, the JSON should always contain one of photo or art_style

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

just double check, on KJ's version, it supports none

Comment thread comfy_extras/nodes_string.py Outdated
Comment thread comfy_extras/nodes_string.py Outdated
Comment thread comfy_extras/nodes_string.py Outdated
Comment thread comfy_extras/nodes_string.py Outdated
@jtydhr88 jtydhr88 force-pushed the feat/ideogram-prompt-nodes branch from 850c913 to d29917b Compare June 23, 2026 02:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@comfy_extras/nodes_color.py`:
- Line 28: The change to use hex_to_rgb(color) in the ColorToRGBInt.execute
method now silently converts invalid hex digits to white instead of raising an
error, which breaks existing node behavior. Replace the hex_to_rgb call with a
stricter validation approach that preserves the original error-raising behavior
for invalid hex input, ensuring that invalid hex values are rejected rather than
defaulting to white, and that the rgb_int output remains consistent with the
actual hex input validation.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 5c1cdc31-f999-4115-bdb1-3955415268b3

📥 Commits

Reviewing files that changed from the base of the PR and between 850c913 and d29917b.

📒 Files selected for processing (7)
  • comfy_api/latest/_io.py
  • comfy_extras/color_util.py
  • comfy_extras/nodes_bounding_boxes.py
  • comfy_extras/nodes_color.py
  • comfy_extras/nodes_json_prompt.py
  • comfy_extras/nodes_string.py
  • nodes.py
🚧 Files skipped from review as they are similar to previous changes (4)
  • nodes.py
  • comfy_extras/nodes_json_prompt.py
  • comfy_extras/color_util.py
  • comfy_extras/nodes_bounding_boxes.py

r = int(color[1:3], 16)
g = int(color[3:5], 16)
b = int(color[5:7], 16)
r, g, b = hex_to_rgb(color)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Preserve strict invalid-hex rejection in ColorToRGBInt.execute.

On Line 28, switching to hex_to_rgb(color) makes invalid hex digits silently become white instead of raising. That changes existing node behavior and can emit mismatched outputs (rgb_int for white, hex still invalid input).

🔧 Proposed fix
     def execute(cls, color: str) -> io.NodeOutput:
         # expect format `#RRGGBB`
         if len(color) != 7 or color[0] != "#":
             raise ValueError("Color must be in format `#RRGGBB`")
+        try:
+            int(color[1:], 16)
+        except ValueError:
+            raise ValueError("Color must be in format `#RRGGBB`")
         r, g, b = hex_to_rgb(color)
 
         rgb_int = r * 256 * 256 + g * 256 + b
         return io.NodeOutput(rgb_int, color)

As per path instructions, comfy_extras/** changes should avoid breaking existing node interfaces.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@comfy_extras/nodes_color.py` at line 28, The change to use hex_to_rgb(color)
in the ColorToRGBInt.execute method now silently converts invalid hex digits to
white instead of raising an error, which breaks existing node behavior. Replace
the hex_to_rgb call with a stricter validation approach that preserves the
original error-raising behavior for invalid hex input, ensuring that invalid hex
values are rejected rather than defaulting to white, and that the rgb_int output
remains consistent with the actual hex input validation.

Source: Path instructions

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants